#pragma once
#include <iostream>
#include<memory>
#include<unordered_map> 
#include"Epoller.hpp"
#include"Connection.hpp"

class Connection;
using connect_t = std::shared_ptr<Connection>;//智能指针对象管理Connection(基类)对象

class EpollServer{
    const static int MAX_EVENTS = 1024;//最大返回就绪事件数
    private:
        bool IsExist(int fd)//判断是否存在该链接（用户级）
        {
            return _connections.find(fd) != _connections.end();
        }
        void TestConnection()
        {
            std::cout<<"ALL CONNECTIONS: ";
            for(auto& conn : _connections){
                std::cout<<conn.first<<" ";
            }
            std::cout<<std::endl;
        }
    public:
        EpollServer()
            :_epoller(new Epoller())
        {
            _epoller->Init();//创建epoll对象fd
        }
        void Add_Connection(connect_t conn)
        {
            auto it = _connections.find(conn->GetFd());
            if(it == _connections.end()){
                //把新链接放入到unordered_map中
                _connections[conn->GetFd()] = conn;
                //注册到内核epoll中
                _epoller->Ctrl(conn->GetFd(),conn->GetEvents(),EPOLL_CTL_ADD);
                //设置关联关系
                conn->SetEpollOwner(this);
            }
            LOG(log_level::DEBUG)<<"Add connection: "<<conn->GetFd();
        }
        void Remove_Connection(int fd)
        {
            if(IsExist(fd)){
                //从内核中移除fd
                _epoller->Ctrl(fd,0,EPOLL_CTL_DEL);
                //关闭fd
                _connections[fd]->Close();
                //从unordered_map中移除fd
                _connections.erase(fd);
                LOG(log_level::DEBUG)<<"Remove connection: "<<fd;
            }
        }
        void Dispach(int num)//派发就绪事件(基于事件驱动)
        {
            for(int i = 0; i < num; i++){//遍历就绪事件
                //派发就绪事件            
                int sockfd = _events[i].data.fd;
                uint32_t ev = _events[i].events;
                if((ev & EPOLLERR) || (ev & EPOLLHUP)){//异常事件，将异常事件转化为读写事件
                    ev = EPOLLIN | EPOLLOUT;
                }else if((ev & EPOLLIN) && IsExist(sockfd)){//读事件就绪，且存在链接
                    _connections[sockfd]->CallRead();
                }else if((ev & EPOLLOUT) && IsExist(sockfd)){//写事件就绪，且存在链接
                    _connections[sockfd]->CallWrite();
                }
            }
        }
        void EnableReadWrite(int fd, bool read, bool write)
        {
            if(IsExist(fd)){
                //修改用户层的事件类型
                uint32_t events = ((read ? EPOLLIN : 0)) | ((write ? EPOLLOUT : 0)|EPOLLET);
                _connections[fd]->SetEvents(events);
                //写入到内核的epoll中(事件更新)
                _epoller->Ctrl(fd,_connections[fd]->GetEvents(),EPOLL_CTL_MOD);//更新

            }
        }
        void LoopOnce(int timeout)
        {
            int num = _epoller->Wait(_events, MAX_EVENTS, timeout);
            Dispach(num);
        }
        void Loop()
        {
            _is_running = true;
            int timeout = -1;
            while(_is_running){
                LoopOnce(timeout);
                TestConnection();
            }
            _is_running = false;
        }
        ~EpollServer()
        {}
    private:
        std::unique_ptr<Epoller> _epoller;//epoll对象智能指针，需要初始化
        std::unordered_map<int, connect_t> _connections;//保存所有连接的fd : Connection的映射表
        bool _is_running = false;
        struct epoll_event _events[MAX_EVENTS];//epoll事件数组
};